package com.sojson.websocket.util;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;

import com.aliyun.oss.ServiceException;
import com.sojson.util.DateUtil;
import com.sojson.util.HexUtil;
import com.sojson.websocket.util.bean.WebSocketConnect;
import com.sojson.websocket.util.enums.EWebSocketControl;
import com.sojson.websocket.util.enums.EWebSocketControlValue;
import com.sojson.websocket.util.enums.EWebSocketGetDataType;

import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;

/**
 * WebSocket工具类
 *
 * @author liu
 * @date 2024-05-31
 */
@Slf4j
public class WebSocketUtil {

    /** 头(注册包) */
    public static final String HEAD_REGISTER = "FAFAFA";
    /** 头(注册包回复) */
    public static final String HEAD_REGISTER_RESULT = "FBFBFB";
    /** 头(心跳包) */
    public static final String HEAD_HEARTBEAT = "FCFCFC";
    /** 头(心跳包回复) */
    public static final String HEAD_HEARTBEAT_RESULT = "FDFDFD";
    /** 头(业务包) */
    public static final String HEAD_BUSINESS = "68";
    /** 结尾 */
    public static final String END = "16";
    /** 采集器 */
    public static final String HARVESTER = "6840";
    /** 其他包 */
    public static final String OTHER_FORTY_ONE =
        "41542B41434B5F5245564953494F4E3D333037415F4E414E5348554F3233303931333032";
    /** 其他包 */
    public static final String OTHER_ZORE_ONE = "000000000001";
    /** 补码(0) */
    public static final String COMP_ZORE = "0";
    /** 值 */
    public static final String ZORE_SIX = "000000";
    /** 操作密码 */
    public static final String PWD = "35333333";
    /** 操作者代码 */
    public static final String HANDLERS = "34896745";
    /** 保留字符 */
    public static final String RETAIN = "33";

    /**
     * 获取报文
     *
     * @param control
     * @param tokenId
     * @param data
     * @return
     */
    private static String getMessage(EWebSocketControl control, String tokenId, String data) {
        String num = HexUtil.toHex((byte)(data.length() / 2));
        StringBuilder str = new StringBuilder(HEAD_BUSINESS);
        str.append(HexUtil.reverse(tokenId));
        str.append(HEAD_BUSINESS);
        str.append(control.getCode());
        str.append(num);
        str.append(data);
        str.append(HexUtil.sumHexAndModule(str.toString()));
        str.append(END);
        return str.toString();
    }

    /**
     * 发送报文
     *
     * @param control
     * @param harvester
     * @param tokenId
     * @param data
     * @return
     */
    private static void sendMessage(EWebSocketControl control, String harvester, String tokenId, String data) {
        String msg = getMessage(control, tokenId, data);

        sendInfo(harvester, msg);
    }

    /**
     * 发送消息
     *
     * @param tokenId
     * @param msg
     */
    private static void sendInfo(String tokenId, String msg) {
        WebSocketConnect connect = WebSocketPoolUtil.get(tokenId);
        if (connect == null || connect.getCtx() == null) {
            throw new ServiceException("WebSocket-此设备未注册: " + tokenId);
        }
        byte[] parseHex = HexUtil.parseHex(msg);

        connect.getCtx().channel().writeAndFlush(Unpooled.copiedBuffer(parseHex));

        log.info(new StringBuilder("WebSocket发送到: ").append(tokenId).append("消息,").append(msg).toString());
    }

    /**
     * 获取数据
     *
     * @param harvester
     * @param tokenId
     * @return
     */
    public static void getData(String harvester, String tokenId) {
        sendMessage(EWebSocketControl.GET_DATA, harvester, tokenId,
            EWebSocketGetDataType.DOSAGE.getAddThirtyThreeReverse());
    }

    /**
     * 获取状态
     *
     * @param harvester
     * @param tokenId
     * @return
     */
    public static void getStatus(String harvester, String tokenId) {
        sendMessage(EWebSocketControl.GET_DATA, harvester, tokenId,
            EWebSocketGetDataType.STATUS.getAddThirtyThreeReverse());
    }

    /**
     * 控阀
     *
     * @param harvester
     * @param tokenId
     * @param controlValue
     * @return
     * @throws Exception
     */
    public static void controlValue(String harvester, String tokenId, EWebSocketControlValue controlValue)
        throws Exception {
        Date date = new Date();
        Instant instant = date.toInstant();
        ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
        LocalDateTime localDateTime = zdt.toLocalDateTime();
        String yyMMddHHmmss = DateUtil.YYYYMMDDHHMMSS.format(localDateTime);

        StringBuilder data = new StringBuilder();
        data.append(PWD);
        data.append(HANDLERS);
        data.append(controlValue.getCode());
        data.append(RETAIN);
        data.append(HexUtil.reverse(HexUtil.addThirtyThree(yyMMddHHmmss)));
        sendMessage(EWebSocketControl.CONTROL_VALUE, harvester, tokenId, data.toString());
    }

    /**
     * 修改IP
     *
     * @param tokenId
     * @return
     */
    @SuppressWarnings("unused")
    private static void updateIp(String tokenId) {
        String data = "AT+W_IP0=116.62.114.108.18888.0";
        WebSocketConnect connect = WebSocketPoolUtil.get(tokenId);
        if (connect == null || connect.getCtx() == null) {
            throw new ServiceException("此设备未注册");
        }
        connect.getCtx().channel().writeAndFlush(Unpooled.copiedBuffer(data.getBytes()));

        log.info(new StringBuilder("WebSocket发送到: ").append(tokenId).append("消息,").append(data).toString());
    }

    /**
     * 修改采集器IP
     *
     * @param tokenId
     * @return
     */
    @SuppressWarnings("unused")
    private static void updateIpHarvester(String tokenId) {
        byte[] data = {0x61, 0x64, 0x6D, 0x69, 0x6E, 0x41, 0x54, 0x2B, 0x42, 0x59, 0x53, 0x4F, 0x43, 0x4B, 0x45, 0x54,
            0x41, 0x3D, 0x54, 0x43, 0x50, 0x2C, 0x31, 0x31, 0x36, 0x2E, 0x36, 0x32, 0x2E, 0x31, 0x31, 0x34, 0x2E, 0x31,
            0x30, 0x38, 0x2C, 0x31, 0x38, 0x38, 0x38, 0x38, 0x0D, 0x0A};
        WebSocketConnect connect = WebSocketPoolUtil.get(tokenId);
        if (connect == null || connect.getCtx() == null) {
            throw new ServiceException("此设备未注册");
        }
        connect.getCtx().channel().writeAndFlush(Unpooled.copiedBuffer(data));

        log.info(new StringBuilder("WebSocket发送到: ").append(tokenId).append("消息,").append(new String(data)).toString());
    }

    /**
     * 修改采集器IP
     *
     * @param tokenId
     * @return
     */
    @SuppressWarnings("unused")
    private static void updateIpRestart(String tokenId) {
        byte[] data = {0x61, 0x64, 0x6D, 0x69, 0x6E, 0x41, 0x54, 0x2B, 0x42, 0x59, 0x53, 0x0D, 0x0A};
        WebSocketConnect connect = WebSocketPoolUtil.get(tokenId);
        if (connect == null || connect.getCtx() == null) {
            throw new ServiceException("此设备未注册");
        }
        connect.getCtx().channel().writeAndFlush(Unpooled.copiedBuffer(data));

        log.info(new StringBuilder("WebSocket发送到: ").append(tokenId).append("消息,").append(new String(data)).toString());
    }

    /**
     * 获取表数据
     *
     * @param meterHex
     * @return
     */
    public static BigDecimal getMeter(String meterHex) {
        BigDecimal oneHundred = new BigDecimal("100");
        BigDecimal sumDecimal = null;
        if (WebSocketUtil.ZORE_SIX.equals(meterHex)) {
            sumDecimal = new BigDecimal(WebSocketUtil.ZORE_SIX);
        } else {
            sumDecimal =
                new BigDecimal(String.valueOf(Integer.parseInt(HexUtil.reverse(meterHex), 16))).divide(oneHundred);
        }
        return sumDecimal;
    }

    /**
     * 获取表数据
     *
     * @param meterHex
     * @return
     */
    public static BigDecimal getMeterTwo(String meterHex) {
        BigDecimal oneHundred = new BigDecimal("100");
        meterHex = HexUtil.subtractThirtyThree(meterHex);
        BigDecimal sumDecimal = null;
        if (WebSocketUtil.ZORE_SIX.equals(meterHex)) {
            sumDecimal = new BigDecimal(WebSocketUtil.ZORE_SIX);
        } else {
            sumDecimal = new BigDecimal(HexUtil.reverse(meterHex)).divide(oneHundred);
        }
        return sumDecimal;
    }

}